<?php

class TMutex
{

private $key;
private $sem_id;
private $is_acquired = false;
private $is_windows = false;
private $filename = '';
private $filepointer;

function __construct()
{
    if(substr(PHP_OS, 0, 3) == 'WIN')
        $this->is_windows = true;
}

/*******************************************************************************
* acquire
*******************************************************************************/
public function init( $aKey = '', $aFilename = '' )
{
    if ( $aFileName == '' )
    {
       $aFileName = $_SERVER["SCRIPT_FILENAME"].".lock";
    }

    if ( $aKey == '' )
    {
        $aKey = TMutex::ftok( $aFilename );
    }

    $this->key = $aKey;

    if( $this->is_windows )
    {
        $this->filename = $aFilename;
    }
    else
    {
        if(!($this->sem_id = sem_get($this->key, 1)))
        {
            print "Error getting semaphore";
            return false;
        }
    }

    return true;
}

/*******************************************************************************
* acquire
*******************************************************************************/
public function acquire()
{
    if($this->is_windows)
    {
        if( ( $this->filepointer = @fopen($this->filename, "w+" ) ) == false)
        {
            print "error opening mutex file<br>";
            return false;
        }

        if(flock($this->filepointer, LOCK_EX) == false)
        {
            print "error locking mutex file<br>";
            return false;
        }
    }
    else
    {
        if (! sem_acquire($this->sem_id))
        {
            print "error acquiring semaphore";
            return false;
        }
    }

    $this->is_acquired = true;
    return true;
}

/*******************************************************************************
* release
*******************************************************************************/
public function release()
{
    if(!$this->is_acquired)
        return true;

    if($this->is_windows)
    {
        if(flock($this->filepointer, LOCK_UN) == false)
        {
            print "error unlocking mutex file<br>";
            return false;
        }

        fclose($this->filepointer);
    }
    else
    {
        if (! sem_release($this->sem_id))
        {
            print "error releasing semaphore";
            return false;
        }
    }

    $this->is_acquired = false;
    return true;
}

/*******************************************************************************
* getId
*******************************************************************************/
public function getId()
{
    return $this->sem_id;
}

/*******************************************************************************
* ftok
*******************************************************************************/
public static function ftok( $aFileName = '' )
{
    if ( $aFileName == '' )
    {
       $aFileName = $_SERVER["SCRIPT_FILENAME"].".lock";
    }

    if ( !file_exists( $aFileName ) )
    {
        @fclose( @fopen( $aFileName, "w+" ) );
    }

    $st = stat( $aFileName );
    if ( !$st )
    {
        return(-1);
    }

    $key = sprintf("%u", (($st['ino'] & 0xffff) | (($st['dev'] & 0xff) << 16) | (($proj_id & 0xff) << 24)));
    return( $key );
}

} // end TMutex

?>
